home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / text / hyper / hsc_source.lha / source / hsc / args.c < prev    next >
C/C++ Source or Header  |  1996-09-30  |  31KB  |  918 lines

  1. /*
  2.  * hsc/args.c
  3.  *
  4.  * user argument handling for hsc
  5.  *
  6.  * Copyright (C) 1995,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 12-Sep-1996
  23.  * created:  1-Jul-1995
  24.  */
  25.  
  26. #include "hsc/global.h"
  27. #include "hsc/status.h"
  28.  
  29. /*
  30.  * ugly includes
  31.  */
  32. #include "ugly/uargs.h"
  33. #include "ugly/fname.h"
  34. #include "ugly/prginfo.h"
  35. #include "ugly/returncd.h"
  36.  
  37. #define DEFAULT_EXTENSION "html"
  38.  
  39. static STRPTR arg_inpfname = NULL;      /* temp vars for set_args() */
  40. static STRPTR arg_outfname = NULL;
  41. static STRPTR arg_extension = NULL;
  42. static LONG arg_quotemode = QMODE_KEEP;
  43. static BOOL arg_mode = FALSE;
  44. static BOOL arg_compact = FALSE;
  45. static BOOL arg_getsize = FALSE;
  46. static BOOL arg_rplc_ent = FALSE;
  47. static BOOL arg_rplc_quote = FALSE;
  48. static BOOL arg_smart_ent = FALSE;
  49. static BOOL arg_jens = FALSE;
  50. static BOOL arg_strip_cmt = FALSE;
  51. static BOOL arg_strip_ext = FALSE;
  52. static BOOL arg_pipe_in = FALSE;
  53. static BOOL arg_license = FALSE;
  54. static BOOL arg_help = FALSE;
  55. static BOOL arg_debug = FALSE;
  56. static STRPTR arg_iconbase = NULL;
  57. static STRPTR arg_striptags = NULL;
  58. #if 0
  59. static LONG arg_entmode = EMODE_KEEP;
  60. #endif
  61.  
  62. static HSCPRC *arg_hp = NULL;
  63.  
  64. /* contains defines for destination-attributes */
  65. static EXPSTR *fileattr_str = NULL;
  66.  
  67. /*
  68.  * cleanup_hsc_args: free local resources
  69.  */
  70. VOID cleanup_hsc_args(VOID)
  71. {
  72.     del_estr(fileattr_str);
  73. }
  74.  
  75. /*
  76.  * arg_ignore
  77.  *
  78.  * argument handler for special values that are passed
  79.  * to "IGNORE=.." several messages are set to be ignored
  80.  * with the old messages left active
  81.  */
  82. static STRPTR arg_ignore_CB(STRPTR arg)
  83. {
  84.     STRPTR errmsg = NULL;
  85.     HSCPRC *hp = arg_hp;
  86.  
  87.     if (!upstrcmp(arg, IGNORE_ALL_STR))
  88.     {                           /* all */
  89.         /* ignore all non-error messages */
  90.         HSCMSG_ID i;
  91.  
  92.         for (i = 0; i < MAX_MSGID; i++)
  93.             hsc_set_msg_ignore(hp, i, TRUE);
  94.     }
  95.     else if (!upstrcmp(arg, IGNORE_BADSTYLE_STR))
  96.     {                           /* bad style */
  97.         /* ignore bad style messages */
  98.         hsc_set_msg_ignore(hp, MSG_CLICK_HERE, TRUE);
  99.         hsc_set_msg_ignore(hp, MSG_SUCC_WHTSPC, TRUE);
  100.         hsc_set_msg_ignore(hp, MSG_PREC_WHTSPC, TRUE);
  101.         hsc_set_msg_ignore(hp, MSG_BLINK_SUX, TRUE);
  102.         hsc_set_msg_ignore(hp, MSG_FRAME_SUX, TRUE);
  103.     }
  104.     else if (!upstrcmp(arg, IGNORE_PORTABILITY_STR))
  105.     {                           /* portability */
  106.         hsc_set_msg_ignore(hp, MSG_EXPT_H1, TRUE);
  107.         hsc_set_msg_ignore(hp, MSG_WRONG_HEADING, TRUE);
  108.         hsc_set_msg_ignore(hp, MSG_ICON_ENTITY, TRUE);
  109.         hsc_set_msg_ignore(hp, MSG_LF_IN_COMMENT, TRUE);
  110.         hsc_set_msg_ignore(hp, MSG_GT_IN_COMMENT, TRUE);
  111.         hsc_set_msg_ignore(hp, MSG_CMTEND_QUOTE, TRUE);
  112.         hsc_set_msg_ignore(hp, MSG_ONEW_COMMENT, TRUE);
  113.     }
  114.     else if (!upstrcmp(arg, IGNORE_JERKS_STR))
  115.     {                           /* jerks */
  116.         /* ignore jerk messages */
  117.         hsc_set_msg_ignore(hp, MSG_TAG_JERK, TRUE);
  118.     }
  119.     else if (!upstrcmp(arg, IGNORE_NOTES_STR))
  120.     {                           /* notes */
  121.         /* ignore note messages */
  122.         hsc_set_msg_ignore(hp, MSG_TAG_STRIPPED, TRUE);
  123.         hsc_set_msg_ignore(hp, MSG_RPLC_ENT, TRUE);
  124.         hsc_set_msg_ignore(hp, MSG_RPLC_SPCCHR, TRUE);
  125.     }
  126.     else
  127.     {
  128.         /* ignore message # */
  129.         LONG ignnum;
  130.  
  131.         if (!str2long(arg, &ignnum))
  132.             errmsg = "illegal ignore";
  133.         else
  134.             hsc_set_msg_ignore(hp, ignnum, TRUE);
  135.     }
  136.  
  137.     return (errmsg);
  138. }
  139.  
  140. /*
  141.  * arg_mode
  142.  *
  143.  * argument handler for values that are passed
  144.  * to "MODE=..". this one resets all ignored
  145.  * messages.
  146.  */
  147. static STRPTR arg_mode_CB(STRPTR arg)
  148. {
  149.     STRPTR errmsg = NULL;
  150.     size_t mode = strenum(arg, MODE_ENUMSTR, '|', STEN_NOCASE);
  151.     HSCPRC *hp = arg_hp;
  152.  
  153.     D(fprintf(stderr, DHSC "args: mode=%s\n", arg));
  154.  
  155.     if (!mode)
  156.         errmsg = "unknown mode";
  157.     else if (mode == MODE_PEDANTIC)
  158.     {                           /* pedantic */
  159.         /* enable all messages */
  160.         HSCMSG_ID i;
  161.  
  162.         for (i = 0; i < MAX_MSGID; i++)
  163.             hsc_set_msg_ignore(hp, i, FALSE);
  164.     }
  165.     else if (mode == MODE_NORMAL)
  166.     {                           /* normal */
  167.         /* ignore note messages */
  168.         arg_mode_CB(MODE_PEDANTIC_STR);
  169.         arg_ignore_CB(IGNORE_NOTES_STR);
  170.         hsc_set_msg_ignore(hp, MSG_MISS_REQTAG, TRUE);
  171.         hsc_set_msg_ignore(hp, MSG_WRONG_HEADING, TRUE);
  172.         hsc_set_msg_ignore(hp, MSG_EXPT_H1, TRUE);
  173.         hsc_set_msg_ignore(hp, MSG_LF_IN_COMMENT, TRUE);
  174.     }
  175.     else if (mode == MODE_RELAXED)
  176.     {                           /* relaxed */
  177.         arg_mode_CB(MODE_NORMAL_STR);
  178.         arg_ignore_CB(IGNORE_BADSTYLE_STR);
  179.         arg_ignore_CB(IGNORE_PORTABILITY_STR);
  180.         arg_ignore_CB(IGNORE_JERKS_STR);
  181.         hsc_set_msg_ignore(hp, MSG_TAG_OBSOLETE, TRUE);
  182.         hsc_set_msg_ignore(hp, MSG_TAG_TOO_OFTEN, TRUE);
  183.         hsc_set_msg_ignore(hp, MSG_CTAG_NESTING, TRUE);
  184.         hsc_set_msg_ignore(hp, MSG_EXPT_SEMIK, TRUE);
  185.     }
  186.     else
  187.     {
  188.         /* ignore message # */
  189.         LONG ignnum;
  190.  
  191.         if (!str2long(arg, &ignnum))
  192.             errmsg = "illegal argument";
  193.         else
  194.             hsc_set_msg_ignore(hp, ignnum, TRUE);
  195.     }
  196.     return (errmsg);
  197. }
  198.  
  199. /*
  200.  * arg_status
  201.  *
  202.  * argument handler for values that are passed
  203.  * to "STATUS=..".
  204.  */
  205. static STRPTR arg_status_CB(STRPTR arg)
  206. {
  207.     STRPTR errmsg = NULL;
  208.     STRPTR argstr = strclone(arg);
  209.     STRPTR argold = argstr;     /* used to call ufree() */
  210. #if DEBUG
  211.     HSCPRC *hp = arg_hp;
  212. #endif
  213.     D(fprintf(stderr, DHSC "args: status=%s\n", arg));
  214.  
  215.     arg = strtok(argstr, "|");
  216.     while (arg)
  217.     {
  218.         if (!upstrcmp(arg, STATUS_QUIET_STR))
  219.             disp_status = STATUS_QUIET;
  220.         else if (!upstrcmp(arg, STATUS_LINE_STR))
  221.             disp_status |= STATUS_LINE;
  222.         else if (!upstrcmp(arg, STATUS_VERSION_STR))
  223.             disp_status |= STATUS_VERSION;
  224.         else if (!upstrcmp(arg, STATUS_VERBOSE_STR))
  225.             disp_status |= STATUS_VERBOSE;
  226.         else if (!upstrcmp(arg, STATUS_FULL_STR))
  227.             disp_status = -1;
  228.         else
  229.             errmsg = "illegal argument";
  230.  
  231.         arg = strtok(NULL, "|");
  232.     }
  233.     ufreestr(argold);
  234.  
  235.     return (errmsg);
  236. }
  237.  
  238. /*
  239.  * show_license
  240.  *
  241.  * display short description of GNU GPL
  242.  */
  243. static VOID show_license(VOID)
  244. {
  245.     STRPTR license =            /* the usual boring text */
  246.     "\nThis program is free software; you can redistribute it and/or modify\n"
  247.     "it under the terms of the GNU General Public License as published by\n"
  248.     "the Free Software Foundation; either version 2 of the License, or\n"
  249.     "(at your option) any later version.\n\n"
  250.  
  251.     "This program is distributed in the hope that it will be useful,\n"
  252.     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  253.     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  254.     "GNU General Public License for more details.\n\n"
  255.  
  256.     "You should have received a copy of the GNU General Public License\n"
  257.     "along with this program; if not, write to the Free Software\n"
  258.     "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n";
  259.  
  260.     fprintf(stderr, license);
  261. }
  262.  
  263. /*
  264.  * set/define_dest_attribs, define_source_attribs
  265.  *
  266.  * set and define attributes for destiantion uri
  267.  */
  268. static VOID set_dest_attribs(HSCPRC * hp, STRPTR destpath, STRPTR destname)
  269. {
  270.     set_estr(fileattr_str, "<$define HSC.DOCUMENT.NAME:string/c=\"");
  271.     if (destname)
  272.         app_estr(fileattr_str, destname);
  273.     app_estr(fileattr_str, "\">\n<$define HSC.DOCUMENT.PATH:string/c=\"");
  274.     if (destname)
  275.         app_estr(fileattr_str, destpath);
  276.     app_estr(fileattr_str, "\">\n<$define HSC.DOCUMENT.URI:string/c=\"");
  277.     if (destname)
  278.         app_estr(fileattr_str, destpath);
  279.     if (destname)
  280.         app_estr(fileattr_str, destname);
  281.     app_estr(fileattr_str, "\">\n");
  282. }
  283.  
  284. /* set_source_attribs */
  285. static VOID set_source_attribs(HSCPRC * hp, STRPTR sourcepath, STRPTR sourcename)
  286. {
  287.     app_estr(fileattr_str, "<$define HSC.SOURCE.NAME:string/c=\"");
  288.     if (sourcename)
  289.         app_estr(fileattr_str, sourcename);
  290.     app_estr(fileattr_str, "\">\n<$define HSC.SOURCE.PATH:string/c=\"");
  291.     if (sourcename)
  292.         app_estr(fileattr_str, sourcepath);
  293.     app_estr(fileattr_str, "\">\n<$define HSC.SOURCE.FILE:string/c=\"");
  294.     if (sourcename)
  295.         app_estr(fileattr_str, sourcepath);
  296.     if (sourcename)
  297.         app_estr(fileattr_str, sourcename);
  298.     app_estr(fileattr_str, "\">\n");
  299. }
  300.  
  301. /* set_file_attribs */
  302. static VOID define_file_attribs(HSCPRC * hp)
  303. {
  304.     hsc_include_string(hp, "[define destattr]", estr2str(fileattr_str),
  305.                        IH_PARSE_HSC | IH_NO_STATUS);
  306.  
  307.     D(fprintf(stderr, DHSC "destination attributes defines:\n%s",
  308.               estr2str(fileattr_str))
  309.         );
  310. }
  311.  
  312. /*
  313.  * user_defines_ok
  314.  *
  315.  * process all defines passed via user args
  316.  *
  317.  * result: always TRUE
  318.  */
  319. BOOL user_defines_ok(HSCPRC * hp)
  320. {
  321.     /* define destination attributes (HSC.DOCUMENT.URI etc.) */
  322.     define_file_attribs(hp);
  323.  
  324.     if (define_list && dll_first(define_list))
  325.     {
  326.         DLNODE *nd = dll_first(define_list);
  327.         EXPSTR *defbuf = init_estr(64);
  328. #if 0
  329.         BOOL old_ignore_quotemsg =
  330.         hsc_get_msg_ignore(hp, MSG_ARG_NO_QUOTE);
  331. #endif
  332.  
  333.         while (nd)
  334.         {
  335.             STRPTR defarg = (STRPTR) dln_data(nd);
  336.  
  337.             D(fprintf(stderr, DHSC "define using `%s'\n", defarg));
  338.  
  339.             set_estr(defbuf, "<$define ");
  340.  
  341.             /* append attribute name */
  342.             do
  343.             {
  344.                 app_estrch(defbuf, defarg[0]);
  345.                 defarg++;
  346.             }
  347.             while (defarg[0] && (defarg[0] != '=')
  348.                    && (defarg[0] != '/') && (defarg[0] != ':'));
  349.  
  350.             /* if no type set, use "string" as default */
  351.             if (defarg[0] != ':')
  352.             {
  353.                 app_estr(defbuf, ":string");
  354.             }
  355.  
  356.             /* append type (if set) and attribute-flags */
  357.             while (defarg[0] && (defarg[0] != '='))
  358.             {
  359.                 app_estrch(defbuf, defarg[0]);
  360.                 defarg++;
  361.             }
  362.  
  363.             /* append value (if any) and quotes */
  364.             if (defarg[0] == '=')
  365.             {
  366.                 char quote_needed = 0;  /* flag: user did not use quotes */
  367.  
  368.                 /* append "=" */
  369.                 app_estrch(defbuf, defarg[0]);
  370.                 defarg++;
  371.  
  372.                 /* check which kind of quote should be appended */
  373.                 if ((defarg[0] != '\"') && (defarg[0] != '\''))
  374.                 {
  375.                     BOOL single_quote = FALSE;
  376.                     BOOL double_quote = FALSE;
  377.                     STRPTR scanarg = defarg;
  378.  
  379.                     /* scan value for quotes */
  380.                     while (scanarg[0])
  381.                     {
  382.                         if (scanarg[0] == '\"')
  383.                             double_quote = TRUE;
  384.                         else if (scanarg[0] == '\'')
  385.                             single_quote = TRUE;
  386.                         scanarg++;
  387.                     }
  388.  
  389.                     /* choose quote to enclose value */
  390.                     if (!double_quote)
  391.                         quote_needed = '\"';
  392.                     else if (!single_quote)
  393.                         quote_needed = '\'';
  394.                     else
  395.                         panic("both quotes in value");
  396.                 }
  397.  
  398.                 /* append quote (if not already done by user) */
  399.                 if (quote_needed)
  400.                     app_estrch(defbuf, quote_needed);
  401.  
  402.                 /* append value */
  403.                 while (defarg[0])
  404.                 {
  405.                     app_estrch(defbuf, defarg[0]);
  406.                     defarg++;
  407.                 }
  408.  
  409.                 /* append quote (if not already done by user) */
  410.                 if (quote_needed)
  411.                     app_estrch(defbuf, quote_needed);
  412.  
  413.             }
  414.  
  415.             /* append end ">" */
  416.             app_estrch(defbuf, '>');
  417.  
  418.             D(fprintf(stderr, DHSC "define: `%s'\n", estr2str(defbuf)));
  419.  
  420.             hsc_include_string(hp, "DEFINE",
  421.                              estr2str(defbuf), IH_PARSE_HSC | IH_NO_STATUS);
  422.             nd = dln_next(nd);
  423.         }
  424.  
  425.         del_estr(defbuf);
  426. #if 0
  427.         hsc_set_msg_ignore(hp, MSG_ARG_NO_QUOTE, old_ignore_quotemsg);
  428. #endif
  429.     }
  430.     else
  431.     {
  432.         D(fprintf(stderr, DHSC "(no defines)\n"));
  433.     }
  434.  
  435.     return ((BOOL) (return_code < RC_ERROR));
  436. }
  437.  
  438. /*
  439.  * args_ok
  440.  *
  441.  * prepare args, check & parse user args, display error and
  442.  * help message if neccessary
  443.  *
  444.  * result: TRUE, if all args ok
  445.  */
  446. BOOL args_ok(HSCPRC * hp, int argc, char *argv[])
  447. {
  448.     BOOL ok;                    /* return value */
  449.     DLLIST *ignore_list = NULL; /* dummy */
  450.     EXPSTR *destdir = init_estr(32);    /* destination dir */
  451.     EXPSTR *rel_destdir = init_estr(32);        /* relative destination dir */
  452.     EXPSTR *kack_name = init_estr(0);   /* temp. str for outfilename */
  453.     struct arglist *hsc_args;   /* argument structure */
  454.  
  455.     arg_hp = hp;
  456.  
  457.     arg_mode_CB(DEFAULT_MODE_STR);
  458.  
  459.     /* create arg-table */
  460.     hsc_args =
  461.         prepare_args("HSC_ARGS",
  462.  
  463.     /* file args */
  464.                      "FROM/M", &incfile,
  465.                      "include- and input-file(s)",
  466.  
  467.                      "TO/K", &arg_outfname,
  468.                      "output file (default: stdout)",
  469.  
  470.                      "PRJFILE/T/K", &prjfilename,
  471.                      "project file (default: none)",
  472.  
  473.                      "PREFSFILE/T/K", &prefsfilename,
  474.                      "syntax preferences (default: hsc.prefs)",
  475.  
  476.                      "MSGFILE=MF/T/K", &msgfilename,
  477.                      "message file (default: stderr)",
  478.  
  479.                      "MSGFORMAT/T/K", &msg_format,
  480.                      "how to display message",
  481.     /* numeric */
  482.                      "MAXERR/N/K", &max_error,
  483.                      "max. number of errors (default: 20)",
  484.  
  485.                      "EXTENSION/T/K", &arg_extension,
  486.                    "output-file-extension (default: " DEFAULT_EXTENSION ")",
  487.  
  488.                      "DEFINE=DEF/T/K/M", &define_list,
  489.                      "define global attribute",
  490.  
  491.                      "IGNORE=IGN/N/K/M/$", arg_ignore_CB, &ignore_list,
  492.                      "ignore message number",
  493.  
  494.                      "MODE/E/K/$", arg_mode_CB, MODE_ENUMSTR, &arg_mode,
  495.                      "mode for syntax check (" MODE_ENUMSTR ")",
  496.  
  497.                      "QUOTESTYLE=QS/E/K", QMODE_ENUMSTR, &arg_quotemode,
  498.                      "defines how quotes appear (" QMODE_ENUMSTR ")",
  499. #if 0
  500.                      "ENTITYSTYLE=ES/E/K", EMODE_ENUMSTR, &entmode,
  501.                      "defines how special chars. appear (" EMODE_ENUMSTR ")",
  502.     /* switches */
  503. #endif
  504.                      "COMPACT=CO/S", &arg_compact,
  505.                      "strip useless LFs and white-spaces",
  506.  
  507.                      "GETSIZE/S", &arg_getsize,
  508.                      "get width and height of images",
  509.  
  510.                      "MSGANSI/S", &msg_ansi,
  511.                      "use ansi-sequences in messages",
  512.  
  513.                      "RPLCENT=RE/S", &arg_rplc_ent,
  514.                      "replace special characters",
  515.  
  516.                      "RPLCQUOTE=RQ/S", &arg_rplc_quote,
  517.                      "replace quotes in text by `"'",
  518.  
  519.                      "SMARTENT=SA/S", &arg_smart_ent,
  520.                      "replace special entities (`&<>\"')",
  521.  
  522.                      "JENS/S", &arg_jens,
  523.                      "don't try this at home",
  524.                      "STRIPCOMMENT=SC/S", &arg_strip_cmt,
  525.                      "strip SGML-comments",
  526.  
  527.                      "STRIPEXTERNAL=SX/S", &arg_strip_ext,
  528.                      "strip tags with external URIs",
  529.  
  530.                      "STRIPTAGS=ST/K", &arg_striptags,
  531.                      "tags to be stripped",
  532.  
  533.                      "ICONBASE/T/K", &arg_iconbase,
  534.                      "base-uri for icon-entities",
  535.  
  536.                      "STATUS/E/K/$", arg_status_CB,
  537.                      STATUS_ENUM_STR, &disp_status,
  538.                      "status message (" STATUS_ENUM_STR ")",
  539.  
  540.                      "-DEBUG/S", &arg_debug, "enable debugging output",
  541.     /* help */
  542.                      "HELP=?/S", &arg_help, "display this text",
  543.                      "LICENSE/S", &arg_license, "display license",
  544.  
  545.                      NULL);
  546.  
  547.     /* remove dummy list TODO: this sucks */
  548.     del_dllist(ignore_list);
  549.  
  550.     ok = (hsc_args != NULL);
  551.  
  552.     /* set & test args */
  553.     if (ok)
  554.     {
  555.         BOOL use_stdout = FALSE;        /* flag: use stdout as output-file */
  556.  
  557.         ok = set_args(argc, argv, hsc_args);
  558.  
  559.         /* display help, if requested vie HELP switch, or no
  560.          * input to pipe or read is passed */
  561.         ok &= (!arg_help &&
  562.                (arg_pipe_in || (incfile && dll_first(incfile))));
  563.  
  564.         if (arg_license)
  565.         {
  566.             /* display license text */
  567.             fprintf_prginfo(stderr);
  568.             show_license();
  569.             set_return_code(RC_WARN);
  570.         }
  571.         else if (!ok)
  572.         {
  573.             /* display help, if error in args or HELP-switch set */
  574.             fprintf_prginfo(stderr);
  575.             fprintf_arghelp(stderr, hsc_args);
  576.             set_return_code(RC_WARN);
  577.         }
  578.         else
  579.         {
  580.             BOOL fnsux = FALSE; /* flag: TRUE = can't evaluate out-filename */
  581.  
  582.             /* set debugging switch */
  583.             hsc_set_debug(hp, arg_debug);
  584.  
  585.             /* autoset depending options */
  586.             if (hsc_get_debug(hp))
  587.                 disp_status = STATUS_VERBOSE;
  588.  
  589.             /* set default options */
  590.             if (!arg_extension)
  591.                 arg_extension = DEFAULT_EXTENSION;
  592.  
  593.             /* disable ID-warning if no project-file */
  594.             if (!prjfilename)
  595.                 hsc_set_msg_ignore(hp, MSG_NO_DOCENTRY, TRUE);
  596.  
  597.             /* compute name of input file */
  598.             arg_inpfname = NULL;
  599.             if (dll_first(incfile) && !arg_pipe_in)
  600.             {
  601.                 /* use last FROM as input file */
  602.                 arg_inpfname = dln_data(dll_last(incfile));
  603.  
  604.                 set_estr(inpfilename, arg_inpfname);
  605.  
  606.                 /* get path part of inputfilename as relative
  607.                  * destination directory */
  608.                 get_fpath(rel_destdir, arg_inpfname);
  609.  
  610.                 /* TODO: set reldir when including first file */
  611.                 /* TODO: find out why the above TODO is there */
  612.  
  613.                 /* remove input filename from incfile */
  614.                 del_dlnode(incfile, dll_last(incfile));
  615.  
  616.                 D(fprintf(stderr, DHSC "input : use `%s'\n"
  617.                           DHSC "reldir: use `%s'\n",
  618.                           estr2str(inpfilename), estr2str(rel_destdir)));
  619.             }
  620.  
  621.             /* display include files */
  622.             D(
  623.                  {
  624.                  DLNODE * nd = dll_first(incfile);
  625.  
  626.                  while (nd)
  627.                  {
  628.                  fprintf(stderr, DHSC "includ: use `%s'\n", (
  629.                                                       STRPTR) dln_data(nd));
  630.                  nd = dln_next(nd);
  631.                  }
  632.                  }
  633.             );
  634.  
  635.             /*
  636.              * if no output-filename given,
  637.              * outfilename stays NULL. this let open_output
  638.              * open stdout as output-file
  639.              */
  640.             if (arg_outfname)
  641.             {
  642.                 /* check, if last char of outputfilename is a
  643.                  * directory separator; if so, use the filename
  644.                  * as destination directory
  645.                  */
  646.                 if (arg_outfname)
  647.                 {
  648.                     UBYTE lastch = 0;
  649.  
  650.                     /* get last char of outfname to determine
  651.                      * if it's a directory
  652.                      */
  653.                     if (strlen(arg_outfname))
  654.                         lastch = arg_outfname[strlen(arg_outfname) - 1];
  655.  
  656. #ifdef AMIGA
  657.                     /* for Amiga, execpt empty string for current dir */
  658.                     if (!lastch)
  659.                     {
  660.                         lastch = (PATH_SEPARATOR[0]);
  661.                         D(fprintf(stderr, DHSC "AMIGA: use current dir\n"));
  662.                     }
  663. #endif
  664.  
  665.                     if (strchr(PATH_SEPARATOR, lastch))
  666.                     {
  667.                         /* use outfilename as destdir */
  668.                         set_estr(destdir, arg_outfname);
  669.                         arg_outfname = NULL;
  670.                         D(fprintf(stderr, DHSC "output: use `%s' as destdir\n",
  671.                                   estr2str(destdir)));
  672.                     }
  673.                     else if (arg_inpfname)
  674.                     {
  675.                         /* output-filename already specified */
  676.                         /* separate it to destdir + reldir + name */
  677.                         EXPSTR *kack_destdir = init_estr(0);
  678.                         EXPSTR *kack_reldir = init_estr(0);
  679.                         STRPTR inp_reldir = estr2str(rel_destdir);
  680.                         STRPTR out_reldir = NULL;
  681.                         STRPTR ou2_reldir = NULL;
  682.  
  683.                         get_fname(kack_name, arg_outfname);
  684.                         get_fpath(kack_destdir, arg_outfname);
  685.  
  686.                         /* check corresponding dirs for
  687.                          * consistency: check if last strlen(rel_destdir)
  688.                          * chars are equal */
  689.                         out_reldir = estr2str(kack_destdir);
  690.                         ou2_reldir = out_reldir;
  691.                         out_reldir = out_reldir
  692.                             + (strlen(out_reldir) - strlen(inp_reldir));
  693.  
  694.                         if (out_reldir[0])
  695.                         {
  696.                             /* search for next dir-sparator backwards */
  697.                             /* (this ones only needed for a smart error message) */
  698.                             while ((out_reldir != ou2_reldir)
  699.                                  && (!strchr(PATH_SEPARATOR, out_reldir[0]))
  700.                                 )
  701.                             {
  702.                                 out_reldir--;
  703.                             }
  704.                             out_reldir++;
  705.                         }
  706.                         D(fprintf(stderr, DHSC "corr_inp: `%s'\n"
  707.                                   DHSC "corr_out: `%s'\n",
  708.                                   inp_reldir, out_reldir)
  709.                             );
  710.  
  711.                         /* check if correspondig relative in/out-dirs
  712.                          * are equal */
  713.                         if (!fnamecmp(inp_reldir, out_reldir))
  714.                         {
  715.                             /* they match.. */
  716.                             STRPTR tmp_name = NULL;     /* copy of kack_nam */
  717.  
  718.                             /* cut corresponding chars */
  719.                             get_left_estr(kack_destdir, kack_destdir,
  720.                                           estrlen(kack_destdir)
  721.                                           - strlen(out_reldir));
  722.  
  723.                             set_estr(kack_reldir, inp_reldir);
  724.  
  725.                             D(fprintf(stderr, DHSC "kack_dst: `%s'\n"
  726.                                       DHSC "kack_rel: `%s'\n"
  727.                                       DHSC "kack_nam: `%s'\n",
  728.                                       estr2str(kack_destdir),
  729.                                       estr2str(kack_reldir),
  730.                                       estr2str(kack_name))
  731.                                 );
  732.  
  733.                             /* just copy these values where they are
  734.                              * expected to be */
  735.                             estrcpy(destdir, kack_destdir);
  736.                             estrcpy(rel_destdir, kack_reldir);
  737.  
  738.                             /* create output filename */
  739.                             tmp_name = strclone(estr2str(kack_name));
  740.                             estrcpy(kack_name, kack_destdir);
  741.                             estrcat(kack_name, kack_reldir);
  742.                             app_estr(kack_name, tmp_name);
  743.                             ufreestr(tmp_name);
  744.  
  745.                             arg_outfname = estr2str(kack_name);
  746.                         }
  747.                         else
  748.                         {
  749.                             /* unmatched corresponding dirs */
  750.                             fprintf(stderr, "unmatched corresponding relative directories:\n"
  751.                                     "  input  `%s'\n  output `%s'\n",
  752.                                     inp_reldir, out_reldir);
  753.                             ok = FALSE;
  754.                         }
  755.  
  756.                         /* free temp. vars */
  757.                         del_estr(kack_reldir);
  758.                         del_estr(kack_destdir);
  759.                     }
  760.                 }
  761.                 if (arg_outfname)
  762.                 {
  763.                     /* set outputfilename with value passed iwithin args */
  764.                     outfilename = init_estr(32);
  765.                     set_estr(outfilename, arg_outfname);
  766.                     D(fprintf(stderr, DHSC "output: set to `%s'\n",
  767.                               estr2str(outfilename)));
  768.                 }
  769.                 else
  770.                 {
  771.                     if (!arg_pipe_in)
  772.                     {
  773.                         /* no outfilename given */
  774.                         /* ->outfilename = destdir + inpfilename + ".html" */
  775.  
  776.                         /* link destdir & input filename */
  777.                         outfilename = init_estr(32);
  778.                         link_fname(outfilename, estr2str(destdir),
  779.                                    arg_inpfname);
  780.                         if (strcmp(arg_extension, "."))
  781.                             set_fext(outfilename, arg_extension);
  782.                         D(fprintf(stderr,
  783.                               DHSC "output: concat destdir+inpfile+`.%s'\n"
  784.                                   DHSC "output: set to `%s'\n",
  785.                                   arg_extension, estr2str(outfilename)));
  786.                     }
  787.                     else
  788.                         fnsux = TRUE;
  789.                 }
  790.  
  791.                 if (fnsux)
  792.                 {
  793.                     /* no way to find out output filename */
  794.                     status_error("unable to evaluate output filename\n");
  795.                     arg_outfname = NULL;
  796.                     ok = FALSE;
  797.                 }
  798.             }
  799.             else
  800.             {
  801.                 D(fprintf(stderr, DHSC "output: use stdout\n"));
  802.                 use_stdout = TRUE;
  803.             }
  804.  
  805.             if (!ok)
  806.                 set_return_code(RC_ERROR);
  807.  
  808.         }
  809.  
  810.         if (ok)
  811.         {
  812.             if (arg_iconbase)
  813.                 hsc_set_iconbase(hp, arg_iconbase);
  814.             if (!use_stdout)
  815.                 hsc_set_filename_document(hp, estr2str(outfilename));
  816.         }
  817.         /* display argument error message */
  818.         if (!ok)
  819.         {
  820.             /* NOTE: no strclone() is used on outfilename, if an
  821.              * error already occured within set_args(). therefore,
  822.              * you must not call ufreestr( outfilename ) */
  823.             pargerr();
  824.             arg_outfname = NULL;
  825.             set_return_code(RC_ERROR);
  826.         }
  827.         else
  828.         {
  829.             EXPSTR *tmp_fname = init_estr(32);  /* filename only part */
  830.  
  831.             fileattr_str = init_estr(64);
  832.  
  833.             if (outfilename)
  834.                 get_fname(tmp_fname, estr2str(outfilename));
  835.             set_dest_attribs(hp, estr2str(rel_destdir),
  836.                              estr2str(tmp_fname));
  837.             if (!arg_pipe_in)
  838.             {
  839.                 if (outfilename)
  840.                     get_fname(tmp_fname, estr2str(outfilename));
  841.                 else
  842.                     clr_estr(tmp_fname);
  843.                 set_source_attribs(hp, estr2str(rel_destdir),
  844.                                    estr2str(tmp_fname));
  845.             }
  846.             else
  847.                 set_source_attribs(hp, NULL, NULL);
  848.  
  849.             D(
  850.                  {
  851.                  HSCMSG_ID i;
  852.  
  853.                  fprintf(stderr, "\n"
  854.                          DHSC "input : `%s'\n", estr2str(inpfilename));
  855.                  fprintf(stderr, DHSC "output: `%s'\n", get_outfilename());
  856.                  fprintf(stderr, DHSC "destdr: `%s'\n", estr2str(destdir));
  857.                 fprintf(stderr, DHSC "reldst: `%s'\n", estr2str(rel_destdir));
  858.                  if (prjfilename)
  859.                  fprintf(stderr, DHSC "projct: `%s'\n", prjfilename);
  860.                  if (!use_stdout)
  861.                 fprintf(stderr, DHSC "procss: `%s'\n", estr2str(outfilename));
  862.                  fprintf(stderr, DHSC "ignore:");
  863.                  for (i = 0; i < MAX_MSGID; i++)
  864.                  if (hsc_get_msg_ignore(hp, i))
  865.                  fprintf(stderr, " %lu", i);
  866.                  fprintf(stderr, "\n");
  867.                  }
  868.             );
  869.  
  870.             del_estr(tmp_fname);
  871.         }
  872.  
  873.         /*
  874.          * set flags of hsc-process
  875.          */
  876.         if (ok)
  877.         {
  878.             hsc_set_chkid(hp, TRUE);
  879.             hsc_set_chkuri(hp, TRUE);
  880.             hsc_set_compact(hp, arg_compact);
  881.             hsc_set_debug(hp, arg_debug);
  882.             hsc_set_getsize(hp, arg_getsize);
  883.             hsc_set_jens(hp, arg_jens);
  884.             hsc_set_rplc_ent(hp, arg_rplc_ent);
  885.             hsc_set_rplc_quote(hp, arg_rplc_quote);
  886.             hsc_set_smart_ent(hp, arg_smart_ent);
  887.             hsc_set_strip_cmt(hp, arg_strip_cmt);
  888.             hsc_set_strip_ext(hp, arg_strip_ext);
  889.  
  890.             hsc_set_quote_mode(hp, arg_quotemode);
  891.  
  892.             /* set directories */
  893.             hsc_set_destdir(hp, estr2str(destdir));
  894.             hsc_set_reldir(hp, estr2str(rel_destdir));
  895.         }
  896.         /* release mem used by args */
  897.         free_args(hsc_args);
  898.     }
  899.     else
  900.     {
  901.         D(
  902.         /* only for developer */
  903.              fprintf(stderr, "ArgDef error: %lu\n", prep_error_num);
  904.             );
  905.     }
  906.  
  907.     del_estr(destdir);
  908.     del_estr(rel_destdir);
  909.     del_estr(kack_name);
  910.  
  911. #if 1
  912.     return (ok);
  913. #else
  914.     return (FALSE);             /* for arg-debugging */
  915. #endif
  916. }
  917.  
  918.